package com.google.code.lf.commons.xml.bind.handler;

import java.io.IOException;
import java.io.Writer;

import com.sun.xml.bind.marshaller.CharacterEscapeHandler;

/**
 * Classe permettant de gérer les échappements de chaînes de caractères dans l'api <a href="https://jaxb.dev.java.net/">JAXB</a>.
 * 
 * @author gael.lorent-fonfrede
 */
public class CustomCharacterEscapeHandler implements CharacterEscapeHandler {
	/* (non-Javadoc)
	 * @see com.sun.xml.bind.marshaller.CharacterEscapeHandler#escape(char[], int, int, boolean, java.io.Writer)
	 */
	public void escape(final char[] buf, final int start, final int len, final boolean isAttValue, final Writer out) throws IOException {
		for (int i=start; i<start+len; i++) {
			final char ch = buf[i];

			// Echappement des échappements xml standards de ponctuation
			// (voir par ex:
			//  http://webdesign.about.com/library/bl_htmlcodes.htm#all
			//  http://webdesign.about.com/od/localization/l/blhtmlcodes-ascii.htm
			//  http://webdesign.about.com/od/localization/l/blhtmlcodes-punc.htm
			//)
			if (ch == '&') {
				out.write("&amp;");
				continue;
			}
			if (ch == '<') {
				out.write("&lt;");
				continue;
			}
			if (ch == '>') {
				out.write("&gt;");
				continue;
			}
			/*if (ch == '~') { // Provoque une explosion ?!
				out.write("&tilde;");
				continue;
			}*/

			// Echappements spécifiques aux attributs
			if ((ch == '"') && isAttValue) {
				out.write("&quot;");
				continue;
			}
			/*if ((ch == '\'') && isAttValue) { // Pas échappé dans Grisbi
				out.write("&apos;");
				continue;
			}*/
			if ((ch == '\n') && isAttValue) {
				out.write("&#10;");
				continue;
			}

			// Echappement des non-ascii (valeur numérique unicode > 128) en valeur hexadécimale (&#xXXXX;)
			// Rmq : les diacritiques accentués entrent dans ce cas de figure général (é, è, etc.)
			// Nécessaire pour respecter le format Grisbi (: le gestionnaire d'échappement par défaut de la JRE traduit en valeur unicode numérique)
			if (ch > 0x7F) {
				out.write("&#x");
				out.write(Integer.toHexString(ch).toUpperCase());
				out.write(";");
				continue;
			}

			// Cas nominal: pas de traitement
			out.write(ch);
		}
	}
}
